package simpleExample;

import gridworld.Environment;

import jade.core.Agent;
import jade.core.behaviours.Behaviour;

import jade.domain.DFService;
import jade.domain.FIPAAgentManagement.DFAgentDescription;

import jade.domain.FIPAAgentManagement.ServiceDescription;

import jade.domain.FIPAException;

import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;

import java.awt.Point;

import java.io.IOException;

import java.util.HashSet;

/* An agent with this behaviour moves in the environment in search for bombs.
 * It keeps a list of position of bombs in the environment and of positions
 * visited in the environment. It registers itself to offer this service.
 */
public class SpotterBehaviour extends Behaviour {
    private Point currentPosition;
    
    String agentName;
    
    //all the bombs known by this agent
    HashSet<Point> bombs;
    
    //all the traps known by this agent
    HashSet<Point> traps;

    private static final MessageTemplate mt = MessageTemplate.or(
                        MessageTemplate.MatchPerformative(ACLMessage.REQUEST),
                        MessageTemplate.MatchPerformative(ACLMessage.INFORM));
    
    public SpotterBehaviour(Agent agent) {
        
        super(agent);
        agentName = agent.getLocalName();
        currentPosition = Environment.getPosition(agentName);
        bombs = new HashSet<Point>();
        traps = new HashSet<Point>();
        DFAgentDescription dfd = new DFAgentDescription();
        dfd.setName(myAgent.getAID());
        ServiceDescription sd = new ServiceDescription();
        sd.setType("spotting-bombs");
        sd.setName("bomb spotter service");
        dfd.addServices(sd);
        try {
          DFService.register(myAgent, dfd);
        } catch (FIPAException e) {
            e.printStackTrace();
        }
    }

    public void action() {
        bombs.addAll(Environment.senseBombs(agentName));
        traps.addAll(Environment.senseTraps(agentName));
        ACLMessage msg = myAgent.receive(mt);
        //we have a message from a carrier
        if(msg != null) {
            if(msg.getPerformative() == ACLMessage.REQUEST) {
                //a request has been made for bombs or traps
                handleInfoRequest(msg);
            } else if(msg.getPerformative() == ACLMessage.INFORM) {
                //remove the bomb from the list
                Point p = SimpleAgent.pointFromString(msg.getContent());
                bombs.remove(p);
            }
        }
        currentPosition = Environment.getPosition(agentName);
        //the spotter does not have a destination
        ((SimpleAgent)myAgent).moveAgent(null);
    }

    public boolean done() {
        return (((SimpleAgent)myAgent).getPositionsToVisit() == 0) &&
            bombs.isEmpty();
    }

    private void handleInfoRequest(ACLMessage request) {
        ACLMessage reply = request.createReply();
        
        if(request.getContent().equals(SimpleAgent.TRAP_REQUEST)) {
            reply.setPerformative(ACLMessage.INFORM);
            handleTrapRequest(reply);
        } else {
            reply.setPerformative(ACLMessage.INFORM_IF);
            handleBombRequest(reply, SimpleAgent.pointFromString(
              request.getContent()));
        }
    }

    private void handleBombRequest(ACLMessage reply, Point position) {
        if(!bombs.isEmpty()) {
            //send message with the nearest bomb
            reply.setContent(SimpleAgent.pointToString(
                                SimpleAgent.getNearestTarget(position, bombs)));
            myAgent.send(reply);
        } else if(((SimpleAgent)myAgent).getPositionsToVisit() == 0) {
            reply.setContent("");
            myAgent.send(reply);
        }
    }

    private void handleTrapRequest(ACLMessage reply) {
        try {
            reply.setContentObject(traps);
        } catch (IOException e) {
            reply.setContent("Exception");
        }
        myAgent.send(reply);
    }
}
